home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / cprog.EXE / GIF2EPS.C < prev    next >
Text File  |  1991-10-07  |  13KB  |  392 lines

  1. /* received on jan 29, 1991 from
  2. Bob Boag                                BITNET:   boag@marshall
  3. Senior Software Systems Analyst         Internet: boag@marshall.wvnet.edu
  4. Marshall University Computer Center     Phone:    (304)696-2624
  5. Huntington, WV 25755-5320               FAX:      (304)696-3601
  6. */
  7.  
  8. /*********************************************
  9.  *                                           *
  10.  *  January 31, 1991 (not much) by John Gay  *
  11.  *                                           *
  12.  * rehacked so that either giftops or        *
  13.  * giftoeps could be compiled.  giftops is   *
  14.  * the default unless the symbol EPS is      *
  15.  * defined.                                  *
  16.  *                                           *
  17.  *********************************************
  18.  *             GIFtoEPS Converter            *
  19.  *                                           *
  20.  *      July 10, 1990  by David S. Joerg     *
  21.  *                                           *
  22.  * cc -DEPS -O -s -o giftoeps \              *
  23.  *                      giftoeps.c -lsys_s   *
  24.  * will give you a nice little 16K binary.   *
  25.  *********************************************
  26.  * If giftoeps does something wrong, you can *
  27.  * email me at... joerg@alliant.mcs.anl.gov  *
  28.  * but I probably won't be much help, I have *
  29.  * no idea whatsoever how this beast really  *
  30.  * works, beacause it's just an overly       *
  31.  * simpleminded kludge of...                 *
  32.  *********************************************
  33.  *             GIFtoPS Converter             *
  34.  *                                           *
  35.  *      May 16, 1988  by Scott Hemphill      *
  36.  *                                           *
  37.  * I wrote this program, and hereby place it *
  38.  * in the public domain, i.e. there are no   *
  39.  * copying restrictions of any kind.         *
  40.  *********************************************/
  41.  
  42. #include <stdio.h>
  43. char *malloc();
  44. int strncmp();
  45.  
  46. #define min(x,y) ((x) < (y) ? (x) : (y))
  47. #define FALSE 0
  48. #define TRUE 1
  49.  
  50. typedef int bool;
  51. typedef struct codestruct {
  52.             struct codestruct *prefix;
  53.             unsigned char first,suffix;
  54.         } codetype;
  55.  
  56. FILE *infile;
  57. unsigned int screenwidth;           /* The dimensions of the screen */
  58. unsigned int screenheight;          /*   (not those of the image)   */
  59. bool global;                        /* Is there a global color map? */
  60. int globalbits;                     /* Number of bits of global colors */
  61. unsigned char globalmap[256][3];    /* RGB values for global color map */
  62. char colortable[256][3];            /* Hex intensity strings for an image */
  63. unsigned char *raster;              /* Decoded image data */
  64. codetype *codetable;                /* LZW compression code data */
  65. int datasize,codesize,codemask;     /* Decoder working variables */
  66. int clear,eoi;                      /* Special code values */
  67.  
  68. void usage()
  69. {
  70. #ifdef EPS
  71.         fprintf(stderr,"usage: giftoeps input-file > output-file\n");
  72. #else
  73.         fprintf(stderr,"usage: giftops input-file > output-file\n");
  74. #endif
  75.         exit(-1);
  76. }
  77.  
  78. void fatal(s)
  79. char *s;
  80. {
  81. #ifdef EPS
  82.         fprintf(stderr,"giftoeps: %s\n",s);
  83. #else
  84.         fprintf(stderr,"giftops: %s\n",s);
  85. #endif
  86.         exit(-1);
  87. }
  88.  
  89. void checksignature()
  90. {
  91.         char buf[6];
  92.  
  93.         fread(buf,1,6,infile);
  94.         if (strncmp(buf,"GIF",3)) fatal("file is not a GIF file");
  95.         if (strncmp(&buf[3],"87a",3)) fatal("unknown GIF version number");
  96. }
  97.  
  98. /* Get information which is global to all the images stored in the file */
  99.  
  100. void readscreen()
  101. {
  102.         unsigned char buf[7];
  103.  
  104.         fread(buf,1,7,infile);
  105.         screenwidth = buf[0] + (buf[1] << 8);
  106.         screenheight = buf[2] + (buf[3] << 8);
  107.         global = buf[4] & 0x80;
  108.         if (global) {
  109.             globalbits = (buf[4] & 0x07) + 1;
  110.             fread(globalmap,3,1<<globalbits,infile);
  111.         }
  112. }
  113.  
  114. /* Convert a color map (local or global) to an array of two character
  115.    hexadecimal strings, stored in colortable.  RGB is converted to
  116.    8-bit grayscale using integer arithmetic. */
  117.  
  118. void initcolors(colortable,colormap,ncolors)
  119. char colortable[256][3];
  120. unsigned char colormap[256][3];
  121. int ncolors;
  122. {
  123.         static char hextab[] = {'0','1','2','3','4','5','6','7',
  124.                                 '8','9','A','B','C','D','E','F'};
  125.         register unsigned color;
  126.         register i;
  127.  
  128.         for (i = 0; i < ncolors; i++) {
  129.             color = 77*colormap[i][0] + 150*colormap[i][1] + 29*colormap[i][2];
  130.             color >>= 8;
  131.             colortable[i][0] = hextab[color >> 4];
  132.             colortable[i][1] = hextab[color & 15];
  133.             colortable[i][2] = '\0';
  134.         }
  135. }
  136.  
  137. /* Write a postscript header to the standard output.  Standard paper size
  138.    (8.5 by 11) is hard-coded, as is the whole initialization sequence.  */
  139. /* (DSJ) - Write an EPS header, try not to hardcode anything. */
  140.  
  141. void writeheader(left,top,width,height)
  142. unsigned left,top,width,height;
  143. {
  144. #ifndef EPS
  145.         double scale;
  146.         int scaledwidth,scaledheight;
  147.  
  148.         scale = min(648.0/screenwidth, 468.0/screenheight);
  149.         scaledwidth = (int)(scale*screenwidth+0.5);
  150.         scaledheight = (int)(scale*screenheight+0.5);
  151.  
  152.         printf("currentscreen /proc exch def /angle exch def /frequency exch def\n");
  153.         printf("/angle 90 def /frequency 60 def\n");
  154.         printf("frequency angle /proc load setscreen\n");
  155. #else
  156.         printf("%%!PS-Adobe-2.0 EPSF-2.0\n");
  157.         printf("%%%%Creator:giftoeps\n");
  158.         printf("%%%%BoundingBox: %f %f %f %f\n\n", 0.0, 0.0, (double)width, (double)height);
  159.         printf("currentscreen 3 1 roll pop pop 60 90 3 -1 roll setscreen\n");
  160. #endif
  161.         printf("/picstr %d string def\n",width);
  162.         printf("/screen {%d %d 8 [%d 0 0 -%d 0 %d]\n",width,height,width,height,height);
  163.         printf("   {currentfile picstr readhexstring pop} image} def\n");
  164. #ifdef EPS
  165.         printf("%d %d scale screen\n", width, height);
  166. #else
  167.         printf("%d %d translate 90 rotate %d %d scale screen\n",
  168.                306+(scaledheight>>1),396-(scaledwidth>>1),
  169.                scaledwidth, scaledheight);
  170. #endif
  171. }
  172.  
  173. /* Output the bytes associated with a code to the raster array */
  174.  
  175. void outcode(p,fill)
  176. register codetype *p;
  177. register unsigned char **fill;
  178. {
  179.         if (p->prefix) outcode(p->prefix,fill);
  180.         *(*fill)++ = p->suffix;
  181. }
  182.  
  183. /* Process a compression code.  "clear" resets the code table.  Otherwise
  184.    make a new code table entry, and output the bytes associated with the
  185.    code. */
  186.  
  187. void process(code,fill)
  188. register code;
  189. unsigned char **fill;
  190. {
  191.         static avail,oldcode;
  192.         register codetype *p;
  193.  
  194.         if (code == clear) {
  195.             codesize = datasize + 1;
  196.             codemask = (1 << codesize) - 1;
  197.             avail = clear + 2;
  198.             oldcode = -1;
  199.         } else if (code < avail) {
  200.             outcode(&codetable[code],fill);
  201.             if (oldcode != -1) {
  202.                 p = &codetable[avail++];
  203.                 p->prefix = &codetable[oldcode];
  204.                 p->first = p->prefix->first;
  205.                 p->suffix = codetable[code].first;
  206.                 if ((avail & codemask) == 0 && avail < 4096) {
  207.                     codesize++;
  208.                     codemask += avail;
  209.                 }
  210.             }
  211.             oldcode = code;
  212.         } else if (code == avail && oldcode != -1) {
  213.             p = &codetable[avail++];
  214.             p->prefix = &codetable[oldcode];
  215.             p->first = p->prefix->first;
  216.             p->suffix = p->first;
  217.             outcode(p,fill);
  218.             if ((avail & codemask) == 0 && avail < 4096) {
  219.                 codesize++;
  220.                 codemask += avail;
  221.             }
  222.             oldcode = code;
  223.         } else {
  224.             fatal("illegal code in raster data");
  225.         }
  226. }
  227.  
  228. /* Decode a raster image */
  229.  
  230. void readraster(width,height)
  231. unsigned width,height;
  232. {
  233.         unsigned char *fill = raster;
  234.         unsigned char buf[255];
  235.         register bits=0;
  236.         register unsigned count,datum=0;
  237.         register unsigned char *ch;
  238.         register int code;
  239.  
  240.         datasize = getc(infile);
  241.         clear = 1 << datasize;
  242.         eoi = clear+1;
  243.         codesize = datasize + 1;
  244.         codemask = (1 << codesize) - 1;
  245.         codetable = (codetype*)malloc(4096*sizeof(codetype));
  246.         if (!codetable) fatal("not enough memory for code table");
  247.         for (code = 0; code < clear; code++) {
  248.             codetable[code].prefix = (codetype*)0;
  249.             codetable[code].first = code;
  250.             codetable[code].suffix = code;
  251.         }
  252.         for (count = getc(infile); count > 0; count = getc(infile)) {
  253.             fread(buf,1,count,infile);
  254.             for (ch=buf; count-- > 0; ch++) {
  255.                 datum += *ch << bits;
  256.                 bits += 8;
  257.                 while (bits >= codesize) {
  258.                     code = datum & codemask;
  259.                     datum >>= codesize;
  260.                     bits -= codesize;
  261.                     if (code == eoi) goto exitloop;  /* This kludge put in
  262.                                                         because some GIF files
  263.                                                         aren't standard */
  264.                     process(code,&fill);
  265.                 }
  266.             }
  267.         }
  268. exitloop:
  269.         if (fill != raster + width*height) fatal("raster has the wrong size");
  270.         free(codetable);
  271. }
  272.  
  273. /* Read a row out of the raster image and write it to the output file */
  274.  
  275. void rasterize(row,width)
  276. int row,width;
  277. {
  278.         register unsigned char *scanline;
  279.         register i;
  280.  
  281.         scanline = raster + row*width;
  282.         for (i = 0; i < width; i++) {
  283.             if (i % 40 == 0) printf("\n");  /* break line every 80 chars */
  284.             fputs(colortable[*scanline++],stdout);
  285.         }
  286.         printf("\n");
  287. }
  288.  
  289. /* write image trailer to standard output */
  290.  
  291. void writetrailer()
  292. {
  293.         printf("showpage\n");
  294. }
  295.  
  296. /* Read image information (position, size, local color map, etc.) and convert
  297.    to postscript. */
  298.  
  299. void readimage()
  300. {
  301.         unsigned char buf[9];
  302.         unsigned left,top,width,height;
  303.         bool local,interleaved;
  304.         char localmap[256][3];
  305.         int localbits;
  306.         int *interleavetable;
  307.         register row;
  308.         register i;
  309.  
  310.         fread(buf,1,9,infile);
  311.         left = buf[0] + (buf[1] << 8);
  312.         top = buf[2] + (buf[3] << 8);
  313.         width = buf[4] + (buf[5] << 8);
  314.         height = buf[6] + (buf[7] << 8);
  315.         local = buf[8] & 0x80;
  316.         interleaved = buf[8] & 0x40;
  317.         if (local) {
  318.             localbits = (buf[8] & 0x7) + 1;
  319.             fread(localmap,3,1<<localbits,infile);
  320.             initcolors(colortable,localmap,1<<localbits);
  321.         } else if (global) {
  322.             initcolors(colortable,globalmap,1<<globalbits);
  323.         } else {
  324.             fatal("no colormap present for image");
  325.         }
  326.         writeheader(left,top,width,height);
  327.         raster = (unsigned char*)malloc(width*height);
  328.         if (!raster) fatal("not enough memory for image");
  329.         readraster(width,height);
  330.         if (interleaved) {
  331.             interleavetable = (int*)malloc(height*sizeof(int));
  332.             if (!interleavetable) fatal("not enough memory for interleave table");
  333.             row = 0;
  334.             for (i = top; i < top+height; i += 8) interleavetable[i] = row++;
  335.             for (i = top+4; i < top+height; i += 8) interleavetable[i] = row++;
  336.             for (i = top+2; i < top+height; i += 4) interleavetable[i] = row++;
  337.             for (i = top+1; i < top+height; i += 2) interleavetable[i] = row++;
  338.             for (row = top; row < top+height; row++) rasterize(interleavetable[row],width);
  339.             free(interleavetable);
  340.         } else {
  341.             for (row = top; row < top+height; row++) rasterize(row,width);
  342.         }
  343.         free(raster);
  344.         writetrailer();
  345. }
  346.  
  347. /* Read a GIF extension block (and do nothing with it). */
  348.  
  349. void readextension()
  350. {
  351.         unsigned char code,count;
  352.         char buf[255];
  353.  
  354.         code = getc(infile);
  355.         while (count = getc(infile)) fread(buf,1,count,infile);
  356. }
  357.  
  358. main(argc,argv)
  359. int argc;
  360. char *argv[];
  361. {
  362.         int quit = FALSE;
  363.         char ch;
  364.  
  365.         if (argc != 2) usage();
  366.         infile = fopen(argv[1],"r");
  367.         if (!infile) {
  368. #ifdef EPS
  369.             perror("giftoeps");
  370. #else
  371.             perror("giftops");
  372. #endif
  373.             exit(-1);
  374.         }
  375.         checksignature();
  376.         readscreen();
  377.         do {
  378.             ch = getc(infile);
  379.             switch (ch) {
  380.                 case '\0':  break;  /* this kludge for non-standard files */
  381.                 case ',':   readimage();
  382.                             break;
  383.                 case ';':   quit = TRUE;
  384.                             break;
  385.                 case '!':   readextension();
  386.                             break;
  387.                 default:    fatal("illegal GIF block type");
  388.                             break;
  389.             }
  390.         } while (!quit);
  391. }
  392.